package com.visikard.ui.fragment;

import java.util.ArrayList;

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.visikard.application.UIMessage;
import com.visikard.application.VKRegApplication;
import com.visikard.asynctask.BaseTask;
import com.visikard.asynctask.GetGiftKardTask;
import com.visikard.item.ItemGiftKardRedeem;
import com.visikard.ui.R;
import com.visikard.ui.activity.PunchRedeemActitivy;
import com.visikard.ui.activity.RingUpRedeemActivity;
import com.visikard.widget.CameraPreview;

public class ScanCodeFragment extends BaseFragment implements Camera.PreviewCallback, com.visikard.widget.ZBarConstants {

	private final int TIME_MER_CLOSE_CAMERA = 60000;

	private RelativeLayout lyCloseCamera;
	private LinearLayout lyCodeAbow, lyCodeBelow;
	private RelativeLayout lyMain;

	private Animation swipeCloseTopAnimation = null;
	private Animation swipeCloseBotAnimation = null;
	private Animation swipeOpenTopAnimation = null;
	private Animation swipeOpenBotAnimation = null;

	/*
	 * stask loader
	 */
	private Context mContext;
	private String mRedemptionCode = "";

	private ArrayList<ItemGiftKardRedeem> mListgiftKards;

	// Camera
	private FrameLayout mContentHolder;
	private ImageView imageView;
	private CameraPreview mPreview;
	private Camera mCamera;
	private ImageScanner mScanner;
	private Handler mAutoFocusHandler;
	private boolean mPreviewing = true;

	static {
		System.loadLibrary("iconv");
	}

	// time close camera
	private CountDownTimer countDownTimer;

	private View.OnClickListener onClickListener;

	private BaseTask mAsyncTask;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View parent = inflater.inflate(R.layout.scan_code_main_fragment, container, false);
		mContext = getActivity();
		innitControl(parent);

		if (!isCameraAvailable()) {
			showDialogNotCamera();
			return parent;
		}

		mAutoFocusHandler = new Handler();

		// Create and configure the ImageScanner;
		setupScanner();

		// Create a RelativeLayout container that will hold a SurfaceView,
		// and set it as the content of our activity.
		mPreview = new CameraPreview(mContext, this, autoFocusCB);
		mContentHolder.addView(mPreview);

		setTimeCloseCamera();

		return parent;
	}

	private void setTimeCloseCamera() {
		countDownTimer = new CountDownTimer(TIME_MER_CLOSE_CAMERA, 1000) {
			@Override
			public void onTick(long millisUntilFinished_) {
			}

			@Override
			public void onFinish() {
				Log.i("NghiDo", "lock time");
				mHandler.sendEmptyMessage(UIMessage.MSG_PAUSE_CAMERA);
			}
		};
		countDownTimer.start();
	}

	private void showDialogNotCamera() {
		AlertDialog mDialog = new AlertDialog.Builder(mContext).setIcon(android.R.drawable.ic_dialog_info)
				.setMessage(R.string.scan_camera_unavailable)
				.setPositiveButton(R.string.literal_ok, new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				}).create();

		mDialog.show();
	}

	private void innitControl(View parent) {

		lyMain = (RelativeLayout) parent.findViewById(R.id.main_layout);
		mContentHolder = (FrameLayout) parent.findViewById(R.id.main_container);
		imageView = (ImageView) parent.findViewById(R.id.imageView);

		lyCloseCamera = (RelativeLayout) parent.findViewById(R.id.layout_close_camera);
		lyCodeAbow = (LinearLayout) parent.findViewById(R.id.layout_scancode_abow);
		lyCodeBelow = (LinearLayout) parent.findViewById(R.id.layout_scancode_below);

		onClickListener = new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				lyCodeAbow.startAnimation(swipeOpenTopAnimation);
				lyCodeBelow.startAnimation(swipeOpenBotAnimation);
			}
		};

		lyCodeAbow.setOnClickListener(onClickListener);
		lyCodeBelow.setOnClickListener(onClickListener);

		lyCloseCamera.setVisibility(View.GONE);
		lyCodeAbow.setVisibility(View.GONE);
		lyCodeBelow.setVisibility(View.GONE);

		initAnimation();
	}

	@Override
	public void onResume() {
		super.onResume();
		mCamera = Camera.open();
		if (mCamera == null) {
			// Cancel request if mCamera is null.
			showDialogNotCamera();
			return;
		}

		Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
		if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
			mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
		}
		else {
			mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
		}

		// mPreview.setCamera(mCamera);
		mPreview.showSurfaceView();

		mPreviewing = true;
	}

	@Override
	public void onPause() {
		super.onPause();

		// Because the Camera object is a shared resource, it's very
		// important to release it when the activity is paused.
		if (mCamera != null) {
			Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
			if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
				mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
			}
			else {
				mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
			}
			// mPreview.setCamera(null);
			mCamera.cancelAutoFocus();
			mCamera.setPreviewCallback(null);
			mCamera.stopPreview();
			mCamera.release();

			// According to Jason Kuang on
			// http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
			// there might be surface recreation problems when the device goes
			// to sleep. So lets just hide it and
			// recreate on resume
			mPreview.hideSurfaceView();

			mPreviewing = false;
			mCamera = null;
		}
	}

	@Override
	public void onDestroyView() {
		// Because the Camera object is a shared resource, it's very
		// important to release it when the activity is paused.
		if (mCamera != null) {
			Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
			if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
				mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
			}
			else {
				mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
			}
			// mPreview.setCamera(null);
			mCamera.cancelAutoFocus();
			mCamera.setPreviewCallback(null);
			mCamera.stopPreview();
			mCamera.release();

			// According to Jason Kuang on
			// http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
			// there might be surface recreation problems when the device goes
			// to sleep. So lets just hide it and
			// recreate on resume
			mPreview.hideSurfaceView();

			mPreviewing = false;
			mCamera = null;
		}
		super.onDestroyView();
	}

	public boolean isCameraAvailable() {
		PackageManager pm = getActivity().getPackageManager();
		return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
	}

	@Override
	public void onPreviewFrame(byte[] data, Camera camera) {
		Camera.Parameters parameters = camera.getParameters();
		Camera.Size size = parameters.getPreviewSize();

		Image barcode = new Image(size.width, size.height, "Y800");
		barcode.setData(data);

		int result = mScanner.scanImage(barcode);
		if (result != 0) {
			imageView.setVisibility(View.GONE);
			mCamera.cancelAutoFocus();
			mCamera.setPreviewCallback(null);
			mCamera.stopPreview();
			mPreviewing = false;
			SymbolSet syms = mScanner.getResults();
			for (Symbol sym : syms) {
				String symData = sym.getData();
				if (!TextUtils.isEmpty(symData)) {
					mRedemptionCode = symData;
					mHandler.sendEmptyMessage(UIMessage.MSG_SCAN_CODE_SUCCESS);
					break;
				}
			}
		}

	}

	public void setupScanner() {
		mScanner = new ImageScanner();
		mScanner.setConfig(0, Config.X_DENSITY, 3);
		mScanner.setConfig(0, Config.Y_DENSITY, 3);

		int[] symbols = getActivity().getIntent().getIntArrayExtra(SCAN_MODES);
		if (symbols != null) {
			mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
			for (int symbol : symbols) {
				mScanner.setConfig(symbol, Config.ENABLE, 1);
			}
		}
	}

	private Runnable doAutoFocus = new Runnable() {
		public void run() {
			if (mCamera != null && mPreviewing) {
				mCamera.autoFocus(autoFocusCB);
			}
		}
	};

	// Mimic continuous auto-focusing
	Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
		public void onAutoFocus(boolean success, Camera camera) {
			mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
		}
	};

	private void gotoRedeemGiftKard() {
		Intent intent = new Intent(getActivity(), RingUpRedeemActivity.class);
		intent.putExtra(RingUpRedeemActivity.EXT_GIFT_KARD_ITEM, mListgiftKards.get(0));
		startActivity(intent);
		getActivity().overridePendingTransition(R.anim.anim_slide_in_from_right, R.anim.anim_slide_out_from_right);
	}

	protected void gotoPunchGiftKard() {
		Intent intent = new Intent(getActivity(), PunchRedeemActitivy.class);
		intent.putExtra(PunchRedeemActitivy.EXT_GIFT_KARD_ITEM, mListgiftKards.get(0));
		startActivity(intent);
		getActivity().overridePendingTransition(R.anim.anim_slide_in_from_right, R.anim.anim_slide_out_from_right);
	}

	private void initAnimation() {
		swipeCloseTopAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_down_to_top);
		swipeCloseTopAnimation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				lyMain.setVisibility(View.GONE);
			}
		});

		swipeCloseBotAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_top_to_down);
		swipeCloseBotAnimation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
				lyCodeAbow.setVisibility(View.VISIBLE);
				lyCodeBelow.setVisibility(View.VISIBLE);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				lyMain.setVisibility(View.GONE);
			}
		});

		swipeOpenTopAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_kard_out_to_top);
		swipeOpenTopAnimation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				lyCodeAbow.setVisibility(View.GONE);
			}
		});

		swipeOpenBotAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_kard_out_to_down);
		swipeOpenBotAnimation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {

			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				lyCodeBelow.setVisibility(View.GONE);
				lyMain.setVisibility(View.VISIBLE);
				imageView.setVisibility(View.VISIBLE);

				mCamera = Camera.open();
				if (mCamera == null) {
					// Cancel request if mCamera is null.
					showDialogNotCamera();
					return;
				}

				Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
				if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
					mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
				}
				else {
					mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
				}

				// mPreview.setCamera(mCamera);
				mPreview.showSurfaceView();

				mPreviewing = true;

				setTimeCloseCamera();
			}
		});
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean handleMessage(Message msg) {
		AlertDialog mDialog;
		switch (msg.what) {
			case UIMessage.MSG_GET_DATA_SUCCESS:
				mListgiftKards = (ArrayList<ItemGiftKardRedeem>) msg.obj;
				if (mListgiftKards != null && mListgiftKards.size() > 0) {
					// branch here
					ItemGiftKardRedeem item = mListgiftKards.get(0);
					if (item.getCampaignType() == 8 && item.getActiveFunkKard() == 0) {
						// go to punch detail
						gotoPunchGiftKard();
					}
					else {
						gotoRedeemGiftKard();
					}
				}
				return true;
			case UIMessage.MSG_INPUT_WRONG_CODE:

				mDialog = new AlertDialog.Builder(mContext).setIcon(android.R.drawable.ic_dialog_info)
						.setMessage(R.string.ringup_scan_wrong_code)
						.setPositiveButton(R.string.literal_ok, new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {
								dialog.cancel();
								mHandler.sendEmptyMessage(UIMessage.MSG_SCAN_CODE_AGAIN);
							}
						}).create();

				mDialog.show();
				return true;
			case UIMessage.MSG_SCAN_CODE_SUCCESS:
				Log.i("NghiDo", "scan code: " + mRedemptionCode);
				if (VKRegApplication.uid == -1 || VKRegApplication.loginSession == null) {
					Toast.makeText(getActivity(), R.string.login_lost, Toast.LENGTH_LONG).show();
				}
				else {
					if (mRedemptionCode != null && mRedemptionCode.length() > 0) {
						if (mAsyncTask != null && !mAsyncTask.isCancelled()) {
							mAsyncTask.cancel(true);
						}
						mAsyncTask = new GetGiftKardTask(mHandler);
						mAsyncTask.execute(VKRegApplication.uid, mRedemptionCode);
					}
					else
						mHandler.sendEmptyMessage(UIMessage.MSG_INPUT_WRONG_CODE);
				}
				return true;
			case UIMessage.MSG_SCAN_CODE_AGAIN:
				if (mCamera != null) {
					Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
					if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
						mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
					}
					else {
						mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
					}
					// mPreview.setCamera(null);
					mCamera.cancelAutoFocus();
					mCamera.setPreviewCallback(null);
					mCamera.stopPreview();
					mCamera.release();

					// According to Jason Kuang on
					// http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
					// there might be surface recreation problems when the device goes
					// to sleep. So lets just hide it and
					// recreate on resume
					mPreview.hideSurfaceView();

					mPreviewing = false;
					mCamera = null;
				}

				mCamera = Camera.open();
				if (mCamera == null) {
					// Cancel request if mCamera is null.
					showDialogNotCamera();
					return true;
				}
				Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
				if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
					mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
				}
				else {
					mPreview.setCamera(mCamera, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
				}

				// mPreview.setCamera(mCamera);
				mPreview.showSurfaceView();

				mPreviewing = true;

				setTimeCloseCamera();
				return true;
			case UIMessage.MSG_CLOSE_CAMERA:
				lyCloseCamera.setVisibility(View.VISIBLE);
				lyCodeAbow.startAnimation(swipeCloseBotAnimation);
				lyCodeBelow.startAnimation(swipeCloseTopAnimation);
				return true;
			case UIMessage.MSG_PAUSE_CAMERA:
				if (mCamera != null) {
					imageView.setVisibility(View.GONE);
					// Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
					cameraInfo = new Camera.CameraInfo();
					if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
						mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK, getActivity());
					}
					else {
						mPreview.setCamera(null, Camera.CameraInfo.CAMERA_FACING_FRONT, getActivity());
					}
					mCamera.cancelAutoFocus();
					mCamera.setPreviewCallback(null);
					mCamera.stopPreview();
					mCamera.release();
					mPreview.hideSurfaceView();
					mPreviewing = false;
					mCamera = null;

					mHandler.sendEmptyMessage(UIMessage.MSG_CLOSE_CAMERA);
				}
				return true;
		}
		return super.handleMessage(msg);
	}

}
